#pragma once
#include "iostream"
#include "string"
#include <list>
#include <map>
#include <iterator>
#include "functional"
#include <algorithm>
#include "fstream"
#include "timer.h"

using namespace std;
// typedef function<double(map<int,int>)> CostfunType;



// 重载 < ：cost比较		== ：cost和Country均相�?
struct Country_Profile {
	friend bool operator<(const Country_Profile p1, const Country_Profile p2) {
		return (p1.Cost < p2.Cost);
	}
	friend bool operator==(const Country_Profile p1, const Country_Profile p2) {
		return (p1.Cost == p2.Cost && p1.Country == p2.Country);
	}
	map<int, double> Country;
	double Cost;
};

struct Imper_Profile {
	friend bool operator<(const Imper_Profile p1, const Imper_Profile p2) {
		return (p1.TotalCost < p2.TotalCost);
	}
	Country_Profile	Imper;
	list<Country_Profile> ColonyList;
	double TotalCost;
};

class ICA {
		int m_dimension;
		list<int> m_ParamIndex;// list of country field Index
		list<double> m_ParamVal;// list of country field value
		double m_ParamVal_max;
		double m_InAcceptableCostVal;// Value of the Country's cost that is not acceptable
		int m_CountryNum;
		int m_ImpNum;
		int m_DecadeNum;
		bool m_IsEqualParamValAllowed;
		double m_RevolutionRate;
		double m_kNumberOfImpact;
		list<Country_Profile> m_CountryList;
		list<Imper_Profile> m_ImperList;

		char* m_LogFileName;
		ofstream m_LogFile;

		ofstream m_PlotFile;
		
		char* m_DataFileName;
		ifstream m_DataFile;

		// CostfunType	Cost;
		CTimer m_Timer;
		// void SetCost(const CostfunType & CostFunc){ Cost = CostFunc;}
		void Assimilate_Clony_to_Imper();
		double Cost(Country_Profile Kingdom);
		void Doing_Revolution();
		void Colony_Imper_swap();
		void CountryCostCalc();
		void Merge_Similar_Impers();
		void InitializeCountries();
		void InitializeImpires();
		void Eliminate_Weakest_Imper();
		// 0~i-1
		int myrandom (int i) {
			int x = rand() % i; // rand()会返回一个从0到最大随机数的任意整数
			return x;
		}
		double myrandomd(double i){
			const int kNumberOfDecimal = 100;
			double x = rand() % int(i*kNumberOfDecimal);
			return x/kNumberOfDecimal;
		}

	public:
		ICA(void);
		ICA(int dimension, int CountryNum, int ImpNum, int DecadeNum, double kNumberOfImpact, double RevolutionRate,
		    bool IsEqualParamValAllowed, double InAcceptableCostVal, char *LogFileName, char *DataFileName);
		~ICA(void);
		void InitializeCountries(map<int, double> *Countries, int n);
		//void InitializeCountries(list<map <int,int> > Countries);
		double Compet(map<int, double> &Imperialist);

};


